0%

SpringAI — 向量存储Elasticsearch

自动配置

Spring AI 为 Elasticsearch Vector Store 提供了 Spring Boot 自动配置。要启用它,请在项目的 Maven pom.xml 或 Gradle build.gradle 文件中添加以下依赖:

Maven

1
2
3
4
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-vector-store-elasticsearch</artifactId>
</dependency>

Gradle

1
2
3
dependencies {
implementation 'org.springframework.ai:spring-ai-starter-vector-store-elasticsearch'
}

针对 Spring Boot 3.3.0 之前版本的额外依赖

对于 Spring Boot 3.3.0 之前的版本,必须显式添加 elasticsearch-java 依赖,且版本需 > 8.13.3,否则旧版本将与所执行的查询不兼容:

Maven

1
2
3
4
5
<dependency>
<groupId>co.elastic.clients</groupId>
<artifactId>elasticsearch-java</artifactId>
<version>8.13.3</version>
</dependency>

Gradle

1
2
3
dependencies {
implementation 'co.elastic.clients:elasticsearch-java:8.13.3'
}

初始化 Schema

向量存储实现可以自动为你初始化所需的 schema,但你需要主动选择启用——通过在相应构造函数中指定 initializeSchema 布尔值,或在 application.properties 文件中设置:

1
spring.ai.vectorstore.elasticsearch.initialize-schema=true

你也可以选择禁用自动初始化,转而使用 Elasticsearch 客户端手动创建索引。这在索引需要高级映射或额外配置时非常有用。


配置参数

请查看向量存储的配置参数列表,了解默认值和可选项。这些属性也可以通过配置 ElasticsearchVectorStoreOptions Bean 来设置。此外,你还需要一个已配置的 EmbeddingModel Bean。

使用示例

配置完成后,你就可以在应用中将 ElasticsearchVectorStore 自动装配(auto-wire)为向量存储使用。


连接配置

要连接 Elasticsearch 并使用 ElasticsearchVectorStore,你需要为实例提供访问详情。最简单的配置方式是通过 Spring Boot 的 application.yml

1
2
3
4
5
6
7
8
9
10
11
spring:
elasticsearch:
uris: http://localhost:9200
username: elastic
password: your-password-here
ai:
vectorstore:
elasticsearch:
index-name: my-vector-index
dimensions: 1536
similarity: cosine

配置属性参考

Spring Elasticsearch 客户端属性

spring.elasticsearch.* 开头的属性用于配置 Elasticsearch 客户端:

属性 描述 默认值
spring.elasticsearch.connection-timeout 与 Elasticsearch 通信时的连接超时时间 1s
spring.elasticsearch.password 认证密码 -
spring.elasticsearch.username 认证用户名 -
spring.elasticsearch.uris 逗号分隔的 Elasticsearch 实例地址列表 http://localhost:9200
spring.elasticsearch.path-prefix 每个请求路径前添加的前缀 -
spring.elasticsearch.restclient.sniffer.delay-after-failure 失败后延迟多久执行一次 sniff 1m
spring.elasticsearch.restclient.sniffer.interval 连续普通 sniff 执行之间的间隔 5m
spring.elasticsearch.restclient.ssl.bundle SSL bundle 名称 -
spring.elasticsearch.socket-keep-alive 是否启用客户端与 Elasticsearch 之间的 socket keep-alive false
spring.elasticsearch.socket-timeout 与 Elasticsearch 通信时的 socket 超时时间 30s

Elasticsearch Vector Store 属性

spring.ai.vectorstore.elasticsearch.* 开头的属性用于配置 ElasticsearchVectorStore

属性 描述 默认值
spring.ai.vectorstore.elasticsearch.initialize-schema 是否初始化所需的 schema false
spring.ai.vectorstore.elasticsearch.index-name 存储向量的索引名称 spring-ai-document-index
spring.ai.vectorstore.elasticsearch.dimensions 向量的维度数量 1536
spring.ai.vectorstore.elasticsearch.similarity 使用的相似度函数 cosine
spring.ai.vectorstore.elasticsearch.embedding-field-name 用于搜索的向量字段名称 embedding

相似度函数

支持以下相似度函数:

函数 说明
cosine 默认值,适用于大多数场景。衡量向量间的余弦相似度。
l2_norm 向量间的欧几里得距离。值越低表示相似度越高。
dot_product 对归一化向量(如 OpenAI embeddings)性能最佳。

元数据过滤

Spring AI 支持可移植的过滤表达式。例如,你可以使用文本表达式语言

1
author == 'John' && year >= 2020

或使用 Filter.Expression DSL 以编程方式构建:

1
2
3
4
5
Filter.Expression filter = new Filter.Expression(
Filter.ExpressionType.AND,
new Filter.Expression(Filter.ExpressionType.EQ, "author", "John"),
new Filter.Expression(Filter.ExpressionType.GTE, "year", 2020)
);

过滤表达式转换示例

例如,以下可移植过滤表达式:

1
country == 'CN' && price < 100

会被转换为 Elasticsearch 专有的过滤格式:

1
2
3
4
5
6
7
8
{
"bool": {
"must": [
{ "term": { "metadata.country": "CN" } },
{ "range": { "metadata.price": { "lt": 100 } } }
]
}
}

手动配置

如果不使用 Spring Boot 自动配置,你可以手动配置 Elasticsearch 向量存储。首先需要将 spring-ai-elasticsearch-store 添加到项目中:

Maven

1
2
3
4
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-elasticsearch-store</artifactId>
</dependency>

Gradle

1
2
3
dependencies {
implementation 'org.springframework.ai:spring-ai-elasticsearch-store'
}

创建 RestClient Bean

创建一个 ElasticsearchRestClient Bean:

1
2
3
4
5
6
@Bean
public ElasticsearchRestClient elasticsearchRestClient() {
RestClient restClient = RestClient.builder(HttpHost.create("http://localhost:9200"))
.build();
return new ElasticsearchRestClient(restClient, new JacksonJsonpMapper());
}

有关自定义 RestClient 配置的更深入信息,请参阅 Elasticsearch 官方文档

使用 Builder 模式创建 VectorStore

然后通过 builder 模式创建 ElasticsearchVectorStore Bean:

1
2
3
4
5
6
7
8
9
10
11
12
@Bean
public VectorStore elasticsearchVectorStore(
ElasticsearchRestClient restClient,
EmbeddingModel embeddingModel) {

return ElasticsearchVectorStore.builder(restClient, embeddingModel)
.indexName("my-custom-index")
.dimensions(1536)
.similarity("cosine")
.initializeSchema(true)
.build();
}

访问原生客户端

ElasticsearchVectorStore 实现通过 getNativeClient() 方法提供了对底层原生 Elasticsearch 客户端(ElasticsearchClient)的访问:

1
2
3
4
5
6
7
8
9
ElasticsearchClient nativeClient =
((ElasticsearchVectorStore) vectorStore).getNativeClient();

// 使用原生客户端执行 Elasticsearch 特有操作
SearchResponse<Object> response = nativeClient.search(s -> s
.index("my-custom-index")
.query(q -> q.matchAll(m -> m)),
Object.class
);

原生客户端使你能够访问通过 VectorStore 接口未暴露的 Elasticsearch 特有功能和操作,例如:

  • 自定义聚合查询
  • 索引管理(创建/删除/更新映射)
  • 批量操作(Bulk API)
  • 集群健康检查
  • 自定义分词器与分析器配置